// -*- c-basic-offset: 2 default-tab-width: 2 indent-tabs-mode: t -*-
// vim: autoindent tabstop=2 noexpandtab shiftwidth=2 softtabstop=2
#ifndef _RMODULE_H_
#define _RMODULE_H_

#include <stdint.h>
#include <llvm/Function.h>

#include "Const.h"
#include "Closure.h"
#include "File.h"

namespace R {
	class Reactor;
	class ConstPool;
	class FunInfo;
	class Formals;

	class RModule {
	public:
		Reactor*      vm;
		uint64_t      moduleId;
		const char*   fileName;
		ConstPool     cpool;
		cpool_entry*  cpool_orig;
		int           nbFuns;
		FunInfo*      funInfos;
		code_segment  cs;
		int           codeSize;
		FunInfo*			entryPoint;
		Environment		*environment;
#if 1
		void**				pic;
#endif

		RModule(Reactor* vm, uint64_t moduleId);

		virtual void tracer(uint64_t closure);

		void load(const char* fileName);

		void createBBs(llvm::Function* func, llvm::BasicBlock** bbs,uint64_t start, uint64_t end);
		void generateCode(llvm::Function* func, uint64_t funcNo);
		template <class T>
		T* loadFromCode(int pc) {
			Any* val = cpool[cs[pc]];
			Assert(Any::isOfType<T>(val), "Unexpected type in constant pool");
			return static_cast<T*>(val);
		}

		virtual void print();

	private:
		// Patch some byte codes
		void patch_bc(); // FIXME this method must be hidden in a more generic one
		// Load a byte code file in memory
		bool load_file(FILE *fd);
		void loadFunInfos(int nb, fun_info *finfos, cpool_entry *cpool_orig);
	};
}
#endif
